
package com.netease.xone.widget;

import java.lang.ref.WeakReference;

import com.netease.config.IConfig;
import com.netease.image.ImageAsyncCallback;
import com.netease.image.ImageManager;
import com.netease.image.ImageType;
import com.netease.image.task.ImageTransaction;
import com.netease.log.NTLog;

import android.content.Context;
import android.graphics.Bitmap;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.ImageView;

/**
 * <p>
 * 异步加载图片ImageView
 * </p>
 * <p>
 * 使用setLoadingImage加载图片
 * </p>
 * <p>
 * 使用setServerClipSize设置图片服务器的裁剪宽高
 * </p>
 */
public class LoadingImageView extends ImageView implements ImageAsyncCallback, IConfig {

    /******************************** IConfig 配置信息 **************************/
    /**
     * 缺省图片类型 可配置项
     *
     * @see IConfig
     */
    public static ImageType DefaultImageType = ImageType.MemCache;
    /************************** 以上 IConfig 配置信息 **************************/

    public static final String TAG = "LoadingImageView";
    private WeakReference<ImageTransaction> mImageTransRef;
    private int mTid;
    private boolean mNeedLoadImageErrorCallBack;// 是否需要在下载出错的情况下回调UI线程的下载出错接口，默认情况关闭
    private int mServerClipWidth, mServerClipHeight;

    public LoadingImageView(Context context) {
        this(context, null, 0);
    }

    public LoadingImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public LoadingImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        doCancel();
    }

    /**
     * 创建异步图片回调
     *
     * @param url 需要完整Http路径
     */
    public void setLoadingImage(String url) {
        setLoadingImage(url, -1, -1);
    }

    /**
     * 创建异步图片回调
     *
     * @param url
     * @param type
     * @see ImageType
     */
    public void setLoadingImage(String url, ImageType type) {
        setLoadingImage(url, -1, -1, type);
    }

    /**
     * 创建异步图片回调
     *
     * @param url
     * @param type
     * @param roundSize
     */
    public void setLoadingImage(String url, ImageType type, int roundSize) {
        setLoadingImage(url, -1, -1, roundSize, type);
    }

    /**
     * 创建异步图片回调
     *
     * @param url
     * @param width
     * @param height
     */
    public void setLoadingImage(String url, int width, int height) {
        setLoadingImage(url, width, height, DefaultImageType);
    }

    /**
     * 创建异步图片回调
     *
     * @param url
     * @param width
     * @param height
     * @param type
     * @see ImageType
     */
    public void setLoadingImage(String url, int width, int height, ImageType type) {
        setLoadingImage(url, width, height, -1, type);
    }

    /**
     * 创建异步图片回调
     *
     * @param imageView
     * @param url
     * @param width 像素
     * @param height 像素
     * @param roundSize 像素
     * @param type
     */
    public void setLoadingImage(String url, int width, int height, int roundSize, ImageType type) {
        doCancel();
        if (TextUtils.isEmpty(url)) {
            setImageDrawable(null);
        } else {
            url = makeServerClipUrl(null, url);// 添加裁剪参数
            ImageManager.getInstance().getImage(url, width, height, roundSize, type, this);
        }
    }

    /**
     * 设置裁剪服务器裁剪图片宽高， 服务器会保持原图宽高比，并匹配设置宽高的最大值进行裁剪， 若不确定宽高中的某一项可以设为0，
     * 至少指定宽高中一个值不为0才会进行裁剪。
     *
     * @param width
     * @param height
     */
    public void setServerClipSize(int width, int height) {
        mServerClipWidth = width;
        mServerClipHeight = height;
    }

    /**
     * 添加图片服务器裁剪参数
     *
     * @param url
     * @return
     */
    private String makeServerClipUrl(String orgUrl, String url) {
        // 有设置任意裁剪参数时
        if (mServerClipWidth > 0 || mServerClipHeight > 0) {
            // 存储在改服务器的图片才能进行裁剪
            if ((orgUrl != null && orgUrl.indexOf("nos=1") > 0
                    || url.startsWith("http://pic.x1.126.net/") || url
                        .startsWith("http://nos.netease.com")) && !url.contains("?resize=")) {
                // 添加裁剪参数?resize=100x100
                StringBuilder sb = new StringBuilder(url);
                sb.append("?resize=").append(mServerClipWidth).append("x")
                        .append(mServerClipHeight);
                // 返回添加参数的地址
                return sb.toString();
            }
        }
        // 返回原地址
        return url;
    }

    /**
     * 设置是否需要加载图片出错的回调
     *
     * @param isNeed
     */
    public void setNeedLoadImageErrorCallBack(boolean isNeed) {
        mNeedLoadImageErrorCallBack = isNeed;
    }

    @Override
    public void startImageTransacion(ImageTransaction trans) {
        if (trans != null) {
            mImageTransRef = new WeakReference<ImageTransaction>(trans);
            mTid = trans.getId();
        }
    }

    /**
     * 判断是否需要调用下载出错时，即bitmap != null时的处理，默认不处理
     */
    @Override
    public boolean onPreUiGetImage(int tid, Bitmap bitmap) {
        return tid == mTid && ((!mNeedLoadImageErrorCallBack || bitmap != null));
    }

    /**
     * 下载图片出错时的UI线程回调，需要打开mNeedLoadImageErrorCallBaack，用于处理某些情况下下载图片出错时载入出错图片
     *
     * @param tid
     */
    public void onUiGetImageNull(int tid) {

    }

    @Override
    public void onUiGetImage(int tid, Bitmap bitmap) {
        // tid = -1时表示直接从缓存拿到了图片没有tid
        if (tid < 0) {
            NTLog.d(TAG, "onUiGetCacheImage");
            if (bitmap == null){
                onUiGetImageNull(tid);
            }else{
                setImageBitmap(bitmap);
            }
        } else if (mTid == tid) {
            NTLog.d(TAG, "onUiGetImage");
            if (bitmap == null){
                onUiGetImageNull(tid);
            }else{
                setImageBitmap(bitmap);
            }
        }
    }

    @Override
    public boolean isValid(int tid) {
        return mTid == tid;
    }

    /**
     * 被回收后进行cancel处理
     */
    public void doCancel() {
        WeakReference<ImageTransaction> imageTransRef = mImageTransRef;
        mImageTransRef = null;
        mTid = 0;
        if (imageTransRef != null) {
            ImageTransaction trans = imageTransRef.get();
            if (trans != null) {
                trans.doCancel();
            }
        }
    }

    @Override
    public String onRedirectUrl(String originalUrl, String redirectUrl) {
        return makeServerClipUrl(originalUrl, redirectUrl);
    }
}
